package org.niux.aims.common.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.niux.aims.models.EntityManagerHelper;

public class DataBackup{
	private Log log = LogFactory.getLog(getClass());
	
	/**
	 * 
	 * 方法概述：获取实体管理器
	 * 描述：获取实体管理器
	 * @return
	 * 返回类型：EntityManager
	 * 修改人：梁铭显
	 * 修改时间：2013-9-17
	 */
	private EntityManager getEntityManager() {
		return EntityManagerHelper.getEntityManager();
	}
	
	/**
	 * 
	 * 方法概述：获取所有表名
	 * 描述：获取所有表名
	 * @return
	 * 返回类型：List<String>
	 * 修改人：梁铭显
	 * 修改时间：2013-9-17
	 */
	@SuppressWarnings("unchecked")
	public List<String> getAllTables(){
		Query query = getEntityManager().createNativeQuery("show tables");
		List<String> tables = query.getResultList();
		
		return tables;
	}
	
	/**
	 * 
	 * 方法概述：获取表结构
	 * 描述：获取表结构
	 * @param tableName
	 * @return
	 * 返回类型：String
	 * 修改人：梁铭显
	 * 修改时间：2013-9-17
	 */
	public String getCreateTableSql(String tableName){
		String sql = "show create table `" + tableName + "`";
		Query query = getEntityManager().createNativeQuery(sql);
		List<?> obj = (List<?>)query.getResultList();
		return ((Object[])obj.get(0))[1].toString();
	}
	
	/**
	 * 
	 * 方法概述：获取表数据
	 * 描述：获取表数据
	 * @param tableName
	 * @return
	 * 返回类型：List<?>
	 * 修改人：梁铭显
	 * 修改时间：2013-9-17
	 */
	@SuppressWarnings("unchecked")
	public List<Vector<Object>> getInsertData(String tableName){
		String sql = "SELECT * FROM " + tableName;
		Query query = getEntityManager().createNativeQuery(sql);
		List<Object[]> objs = (List<Object[]>)query.getResultList();
		
		List<Vector<Object>> list = new ArrayList<Vector<Object>>();
		
		for (Object[] obj : objs) {
			Vector<Object> vector = new Vector<Object>();
			for (int i = 0; i < obj.length; i++) {
				vector.add(obj[i]);
			}
			
			list.add(vector);
		}
		return list;
	}
	
	/**
	 * 
	 * 方法概述：获取列名
	 * 描述：获取列名
	 * @param tableName
	 * @return
	 * 返回类型：List<?>
	 * 修改人：梁铭显
	 * 修改时间：2013-9-17
	 */
	public List<?> getDescribe(String tableName){
		String sql = "describe `"+tableName+"`";
		Query query = getEntityManager().createNativeQuery(sql);
		return (List<?>)query.getResultList();
	}
	
	/**
	 * 
	 * 方法概述：备份数据库
	 * 描述：备份数据库
	 * 返回类型：void
	 * 修改人：梁铭显
	 * 修改时间：2013-9-17
	 */
	public boolean backup(String path){
		List<String> tables = getAllTables();
		
		StringBuffer sql = new StringBuffer();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		//备份文件说明
		sql.append("/*\r\n");
		sql.append("权限管理系统数据库备份\r\n");
		sql.append("\r\n");
		sql.append("备份服务器	：本机\r\n");
		sql.append("数据库服务器	：MYSQL\r\n");
		sql.append("数据库编码	：utf-8\r\n");
		sql.append("\r\n");
		sql.append("备份时间	："+dateFormat.format(new Date())+"\r\n");
		sql.append("备份数据库	：aims\r\n");
		sql.append("*/\r\n");
		sql.append("\r\n");
		
		sql.append("SET FOREIGN_KEY_CHECKS=0;\r\n");
		
		for (String table : tables) {
			//表说明
			sql.append("\r\n");
			sql.append("-- ----------------------------\r\n");
			sql.append("-- Table structure for `"+table+"`\r\n");
			sql.append("-- ----------------------------\r\n");
			sql.append("DROP TABLE IF EXISTS `"+table+"`;\r\n");
			//表结构
			sql.append(getCreateTableSql(table).replaceAll("\n", "")+";");
			sql.append("\r\n");
			sql.append("\r\n");
			
			//数据说明
			sql.append("-- ----------------------------\r\n");
			sql.append("-- Records of "+table+"\r\n");
			sql.append("-- ----------------------------\r\n");
			
			//插入数据
			if(!table.equals("logs")){
				List<Vector<Object>> datas = getInsertData(table);
				for (Vector<Object> data : datas) {
					String tempStr = data.toString();
		        	tempStr =tempStr.substring(1, tempStr.length()-1);
		        	tempStr ="INSERT INTO " + "`"+ table + "`" + " VALUES(" + transformValuesStr(tempStr).trim() + ");";
		        	sql.append(tempStr + "\r\n");
				}
			}
		}
		
		log.debug(sql.toString());
		boolean flag = exportToFile(sql.toString(),path);
		return flag;
	}
	
	/**
	 * 
	 * 方法概述：导出备份文件
	 * 描述：导出备份文件
	 * @param text
	 * @param path
	 * 返回类型：void
	 * 修改人：梁铭显
	 * 修改时间：2013-9-23
	 */
	public boolean exportToFile(String text,String path){
		SimpleDateFormat smf = new SimpleDateFormat("yyyy:MM:dd:HH:mm:ss");
		String file_separator = System.getProperty("file.separator");
		
		File tempFile =new File(path + "/backup");
		
		if(!tempFile.exists()){
			tempFile.mkdir();
		}
		
		File file = new File(tempFile.getPath() + file_separator + "aims_" + smf.format(new Date()).replaceAll(" |:", "") + ".sql");
		
		if(!file.exists()){
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
		}
		
		try {
			PrintWriter pwrite = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,false), "UTF8"));
			pwrite.println(text);
			pwrite.flush();
			pwrite.close();
			return true;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return false;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		}
	}
	
	/**
	 * 
	 * 方法概述：字符串处理
	 * 描述：字符串处理
	 * @param str
	 * @return
	 * 返回类型：String
	 * 修改人：梁铭显
	 * 修改时间：2013-9-18
	 */
	public String transformValuesStr(String str){
		String[] tempArr = str.split(",");
		StringBuffer tempStr = new StringBuffer();
		
		for (int i = 0; i < tempArr.length; i++) {
			if(tempArr[i].trim().equals("null")){
				tempStr.append(tempArr[i].trim()+",");
			} else {
				tempStr.append("'"+tempArr[i].trim()+"',");
			}
		}
		
		return tempStr.substring(0, tempStr.length() - 1).toString();
	}
	
	/**
	 * 
	 * 方法概述：读取备份文件
	 * 描述：读取备份文件
	 * @param fileName
	 * 返回类型：void
	 * 修改人：梁铭显
	 * 修改时间：2013-9-23
	 */
	public boolean getBackupFile(String fileName){
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName),"utf-8"));
			
			 String tempString = null;
			 
			while ((tempString = reader.readLine()) != null) {
				int index = tempString.indexOf(";");
				if (-1 != index) {
					excuteSql(tempString);
				}
            }
			
			reader.close();
			return true;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}
	
	/**
	 * 
	 * 方法概述：执行SQL脚本语句
	 * 描述：执行SQL脚本语句
	 * @param sql
	 * 返回类型：void
	 * 修改人：梁铭显
	 * 修改时间：2013-9-23
	 */
	public void excuteSql(String sql){
//		if(sql.contains("DROP TABLE IF EXISTS `logs`") || sql.contains("CREATE TABLE `logs`")){
//			return;
//		}
		
		getEntityManager().getTransaction().begin();
		Query query = getEntityManager().createNativeQuery(sql.replace(";", ""));
		query.executeUpdate();
		getEntityManager().getTransaction().commit();
	}
}
